#include<stdio.h>
#include "calc.h"
#include "calc.tab.h"

int dfs(nodeType* p) {
   
   if (!p) return 0;

   switch (p->type) {
   
      case typeCon:
         return p->con_or_id.value_or_i;

      case typeId:
         return symtab[p->con_or_id.value_or_i];

      case typeOpr:
 
          switch (p->opr.oper) {
   
             case WHILE:
                while (dfs (p->opr.op[0]))
                   dfs(p->opr.op[1]);
                return 0;

             case IF:
                if (dfs (p->opr.op[0]))
                   dfs(p->opr.op[1]);
                else if (p->opr.nops > 2)
                   dfs(p->opr.op[2]);
                return 0;
  
             case PRINT:
                printf ("%d\n", dfs (p->opr.op[0]));
                return 0;

             case ';':
                dfs (p->opr.op[0]);
                return dfs (p->opr.op[1]);
  
             case '=':
                return symtab[p->opr.op[0]->con_or_id.value_or_i] = dfs (p->opr.op[1]);

             case UMINUS:
                return - dfs(p->opr.op[0]);

             case '+':
                return dfs(p->opr.op[0]) + dfs(p->opr.op[1]);

             case '-':
                return dfs(p->opr.op[0]) - dfs(p->opr.op[1]);

             case '*':
                return dfs(p->opr.op[0]) * dfs(p->opr.op[1]);

             case '/':
                return dfs(p->opr.op[0]) / dfs(p->opr.op[1]);

             case '^':
                return pow(dfs(p->opr.op[0]),  dfs(p->opr.op[1]));

             case '<':
                return dfs(p->opr.op[0]) < dfs(p->opr.op[1]);

             case '>':
                return dfs(p->opr.op[0]) > dfs(p->opr.op[1]);

             case GE:
                return dfs(p->opr.op[0]) >= dfs(p->opr.op[1]);

             case LE:
                return dfs(p->opr.op[0]) <= dfs(p->opr.op[1]);

             case NE:
                return dfs(p->opr.op[0]) != dfs(p->opr.op[1]);

             case EQ:
                return dfs(p->opr.op[0]) == dfs(p->opr.op[1]);
      }
   }
}
